#include "ffdemuxer.h"
#include "queue/ffapacketqueue.h"
#include "queue/ffvpacketqueue.h"
#include <iostream>

FFDemuxer::FFDemuxer()
{}

FFDemuxer::~FFDemuxer() {
    close();
}


void FFDemuxer::init(const std::string &url_, const std::string &format_, FFAPacketQueue *aPktQueue_, FFVPacketQueue *vPktQueue_)
{
    url = url_;
    format = format_;
    aPktQueue = aPktQueue_;
    vPktQueue = vPktQueue_;

    initDemuxer();
}


int FFDemuxer::demux()
{
    AVPacket* packet = av_packet_alloc();
    av_init_packet(packet);

    int ret = av_read_frame(fmtCtx,packet);

    if(ret < 0){
        if(ret == AVERROR_EOF){

            if(aPktQueue)
                aPktQueue->enqueueNull();
            if(vPktQueue)
                vPktQueue->enqueueNull();
            std::cout<<"AVERROR_EOF"<<std::endl;
            return 1;
        }
        else{
            printError(ret);
            avformat_close_input(&fmtCtx);
            av_packet_free(&packet);
            return -1;
        }
    }

    if(aStream && packet->stream_index == aStream->index){
        if(aPktQueue)
            aPktQueue->enqueue(packet);
//        std::cout << "stream: audio" <<std::endl;
     }
    else if(vStream && packet->stream_index == vStream->index){
        if(vPktQueue)
            vPktQueue->enqueue(packet);
//        std::cout << "stream pakcet: video" <<std::endl;
    }

    av_packet_free(&packet);

    return 0;
}

AVStream *FFDemuxer::getAStream()
{
    return aStream;
}

AVStream *FFDemuxer::getVStream()
{
    return vStream;
}

void FFDemuxer::wakeAllThread()
{
    if(vPktQueue)
        vPktQueue->wakeAllThread();
    if(aPktQueue)
        aPktQueue->wakeAllThread();
}

void FFDemuxer::close()
{
    if (fmtCtx) {
        avformat_close_input(&fmtCtx);
    }
}


void FFDemuxer::printError(int ret)
{
    char errorBuffer[AV_ERROR_MAX_STRING_SIZE];
    int res = av_strerror(ret,errorBuffer,sizeof errorBuffer);
    if(res < 0){
        std::cerr << "Unknow Error!"<<std::endl;
    }
    else{
        std::cerr<<"Error:"<<errorBuffer<<std::endl;
    }

}

void FFDemuxer::initDemuxer()
{
    avformat_network_init();
    avdevice_register_all();

#if 0
    int cores = av_cpu_count() >> 1;
    av_dict_set(&opts,"threads",std::to_string(cores).c_str(),0); //多线程解复用
#endif
    inputFmt = av_find_input_format(format.c_str());
    int ret = avformat_open_input(&fmtCtx,url.c_str(),inputFmt,&opts);
    if(ret < 0){
        avformat_close_input(&fmtCtx);
        printError(ret);
        return;
    }

    ret = avformat_find_stream_info(fmtCtx,nullptr);
    if(ret < 0){
        avformat_close_input(&fmtCtx);
        printError(ret);
        return;
    }

    for(size_t i = 0;i < fmtCtx->nb_streams; ++i){
        AVStream* stream = fmtCtx->streams[i];
        AVCodecParameters*codecPar = stream->codecpar;

        if(codecPar->codec_type == AVMEDIA_TYPE_AUDIO){
            aStream = stream;
            aTimeBase = stream->time_base;
        }
        else if(codecPar->codec_type == AVMEDIA_TYPE_VIDEO){
            vStream = stream;
            vTimeBase = stream->time_base;
        }
    }
}


